home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / src / gcc-2.7.0-amiga / cp / g++.c < prev    next >
C/C++ Source or Header  |  1995-08-24  |  13KB  |  591 lines

  1. /* G++ preliminary semantic processing for the compiler driver.
  2.    Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
  3.    Contributed by Brendan Kehoe (brendan@cygnus.com).
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.  */
  21.  
  22. /* This program is a wrapper to the main `gcc' driver.  For GNU C++,
  23.    we need to do two special things: a) append `-lg++' in situations
  24.    where it's appropriate, to link in libg++, and b) add `-xc++'..`-xnone'
  25.    around file arguments named `foo.c' or `foo.i'.  So, we do all of
  26.    this semantic processing then just exec gcc with the new argument
  27.    list.
  28.  
  29.    We used to do all of this in a small shell script, but many users
  30.    found the performance of this as a shell script to be unacceptable.
  31.    In situations where your PATH has a lot of NFS-mounted directories,
  32.    using a script that runs sed and other things would be a nasty
  33.    performance hit.  With this program, we never search the PATH at all.  */
  34.  
  35. #include "config.h"
  36. #ifdef __STDC__
  37. #include <stdarg.h>
  38. #else
  39. #include <varargs.h>
  40. #endif
  41. #include <stdio.h>
  42. #include <sys/types.h>
  43. #ifndef _WIN32
  44. #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
  45. #else
  46. #include <process.h>
  47. #endif
  48. #include <errno.h>
  49.  
  50. /* Defined to the name of the compiler; if using a cross compiler, the
  51.    Makefile should compile this file with the proper name
  52.    (e.g., "i386-aout-gcc").  */
  53. #ifndef GCC_NAME
  54. #define GCC_NAME "gcc"
  55. #endif
  56.  
  57. /* This bit is set if we saw a `-xfoo' language specification.  */
  58. #define LANGSPEC    (1<<1)
  59. /* This bit is set if they did `-lm' or `-lmath'.  */
  60. #define MATHLIB        (1<<2)
  61.  
  62. /* On MSDOS, write temp files in current dir
  63.    because there's no place else we can expect to use.  */
  64. #ifdef __MSDOS__
  65. #ifndef P_tmpdir
  66. #define P_tmpdir "."
  67. #endif
  68. #ifndef R_OK
  69. #define R_OK 4
  70. #define W_OK 2
  71. #define X_OK 1
  72. #endif
  73. #endif
  74.  
  75. #ifndef VPROTO
  76. #ifdef __STDC__
  77. #define PVPROTO(ARGS)        ARGS
  78. #define VPROTO(ARGS)        ARGS
  79. #define VA_START(va_list,var)    va_start(va_list,var)
  80. #else
  81. #define PVPROTO(ARGS)        ()
  82. #define VPROTO(ARGS)        (va_alist) va_dcl
  83. #define VA_START(va_list,var)    va_start(va_list)
  84. #endif
  85. #endif
  86.  
  87. #ifndef errno
  88. extern int errno;
  89. #endif
  90.  
  91. extern int sys_nerr;
  92. #ifndef HAVE_STRERROR
  93. #if defined(bsd4_4)
  94. extern const char *const sys_errlist[];
  95. #else
  96. extern char *sys_errlist[];
  97. #endif
  98. #else
  99. extern char *strerror();
  100. #endif
  101.  
  102. /* Name with which this program was invoked.  */
  103. static char *programname;
  104.  
  105. char *
  106. my_strerror(e)
  107.      int e;
  108. {
  109.  
  110. #ifdef HAVE_STRERROR
  111.   return strerror(e);
  112.  
  113. #else
  114.  
  115.   static char buffer[30];
  116.   if (!e)
  117.     return "";
  118.  
  119.   if (e > 0 && e < sys_nerr)
  120.     return sys_errlist[e];
  121.  
  122.   sprintf (buffer, "Unknown error %d", e);
  123.   return buffer;
  124. #endif
  125. }
  126.  
  127. #ifdef HAVE_VPRINTF
  128. /* Output an error message and exit */
  129.  
  130. static void
  131. fatal VPROTO((char *format, ...))
  132. {
  133. #ifndef __STDC__
  134.   char *format;
  135. #endif
  136.   va_list ap;
  137.  
  138.   VA_START (ap, format);
  139.  
  140. #ifndef __STDC__
  141.   format = va_arg (ap, char*);
  142. #endif
  143.  
  144.   fprintf (stderr, "%s: ", programname);
  145.   vfprintf (stderr, format, ap);
  146.   va_end (ap);
  147.   fprintf (stderr, "\n");
  148. #if 0
  149.   /* XXX Not needed for g++ driver.  */
  150.   delete_temp_files ();
  151. #endif
  152.   exit (1);
  153. }
  154.  
  155. static void
  156. error VPROTO((char *format, ...))
  157. {
  158. #ifndef __STDC__
  159.   char *format;
  160. #endif
  161.   va_list ap;
  162.  
  163.   VA_START (ap, format);
  164.  
  165. #ifndef __STDC__
  166.   format = va_arg (ap, char*);
  167. #endif
  168.  
  169.   fprintf (stderr, "%s: ", programname);
  170.   vfprintf (stderr, format, ap);
  171.   va_end (ap);
  172.  
  173.   fprintf (stderr, "\n");
  174. }
  175.  
  176. #else /* not HAVE_VPRINTF */
  177.  
  178. static void
  179. error (msg, arg1, arg2)
  180.      char *msg, *arg1, *arg2;
  181. {
  182.   fprintf (stderr, "%s: ", programname);
  183.   fprintf (stderr, msg, arg1, arg2);
  184.   fprintf (stderr, "\n");
  185. }
  186.  
  187. static void
  188. fatal (msg, arg1, arg2)
  189.      char *msg, *arg1, *arg2;
  190. {
  191.   error (msg, arg1, arg2);
  192. #if 0
  193.   /* XXX Not needed for g++ driver.  */
  194.   delete_temp_files ();
  195. #endif
  196.   exit (1);
  197. }
  198.  
  199. #endif /* not HAVE_VPRINTF */
  200.  
  201. /* More 'friendly' abort that prints the line and file.
  202.    config.h can #define abort fancy_abort if you like that sort of thing.  */
  203.  
  204. void
  205. fancy_abort ()
  206. {
  207.   fatal ("Internal g++ abort.");
  208. }
  209.  
  210. char *
  211. xmalloc (size)
  212.      unsigned size;
  213. {
  214.   register char *value = (char *) malloc (size);
  215.   if (value == 0)
  216.     fatal ("virtual memory exhausted");
  217.   return value;
  218. }
  219.  
  220. /* Return a newly-allocated string whose contents concatenate those
  221.    of s1, s2, s3.  */
  222. static char *
  223. concat (s1, s2, s3)
  224.      char *s1, *s2, *s3;
  225. {
  226.   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  227.   char *result = xmalloc (len1 + len2 + len3 + 1);
  228.  
  229.   strcpy (result, s1);
  230.   strcpy (result + len1, s2);
  231.   strcpy (result + len1 + len2, s3);
  232.   *(result + len1 + len2 + len3) = 0;
  233.  
  234.   return result;
  235. }
  236.  
  237. static void
  238. pfatal_with_name (name)
  239.      char *name;
  240. {
  241.   char *s;
  242.  
  243.   if (errno < sys_nerr)
  244. #ifdef HAVE_STRERROR
  245.     s = concat ("%s: ", strerror(errno), "");
  246. #else
  247.     s = concat ("%s: ", sys_errlist[errno], "");
  248. #endif
  249.   else
  250.     s = "cannot open %s";
  251.   fatal (s, name);
  252. }
  253.  
  254. #ifdef __MSDOS__
  255. /* This is the common prefix we use to make temp file names.  */
  256. char *temp_filename;
  257.  
  258. /* Length of the prefix.  */
  259. int temp_filename_length;
  260.  
  261. /* Compute a string to use as the base of all temporary file names.  */
  262. static char *
  263. choose_temp_base_try (try, base)
  264. char *try;
  265. char *base;
  266. {
  267.   char *rv;
  268.   if (base)
  269.     rv = base;
  270.   else if (try == (char *)0)
  271.     rv = 0;
  272.   else if (access (try, R_OK | W_OK) != 0)
  273.     rv = 0;
  274.   else
  275.     rv = try;
  276.   return rv;
  277. }
  278.  
  279. static void
  280. choose_temp_base ()
  281. {
  282.   char *base = 0;
  283.   int len;
  284.  
  285.   base = choose_temp_base_try (getenv ("TMPDIR"), base);
  286.   base = choose_temp_base_try (getenv ("TMP"), base);
  287.   base = choose_temp_base_try (getenv ("TEMP"), base);
  288.  
  289. #ifdef P_tmpdir
  290.   base = choose_temp_base_try (P_tmpdir, base);
  291. #endif
  292.  
  293.   base = choose_temp_base_try ("/usr/tmp", base);
  294.   base = choose_temp_base_try ("/tmp", base);
  295.  
  296.   /* If all else fails, use the current directory! */  
  297.   if (base == (char *)0)
  298.     base = "./";
  299.  
  300.   len = strlen (base);
  301.   temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
  302.   strcpy (temp_filename, base);
  303.   if (len > 0 && temp_filename[len-1] != '/')
  304.     temp_filename[len++] = '/';
  305.   strcpy (temp_filename + len, "ccXXXXXX");
  306.  
  307.   mktemp (temp_filename);
  308.   temp_filename_length = strlen (temp_filename);
  309.   if (temp_filename_length == 0)
  310.     abort ();
  311. }
  312.  
  313. static void
  314. perror_exec (name)
  315.      char *name;
  316. {
  317.   char *s;
  318.  
  319.   if (errno < sys_nerr)
  320.     s = concat ("installation problem, cannot exec %s: ",
  321.         my_strerror( errno ), "");
  322.   else
  323.     s = "installation problem, cannot exec %s";
  324.   error (s, name);
  325. }
  326.  
  327. /* This is almost exactly what's in gcc.c:pexecute for MSDOS.  */
  328. void
  329. run_dos (program, argv)
  330.      char *program;
  331.      char *argv[];
  332. {
  333.   char *scmd, *rf;
  334.   FILE *argfile;
  335.   int i;
  336.  
  337.   choose_temp_base (); /* not in gcc.c */
  338.  
  339.   scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
  340.   rf = scmd + strlen (program) + 6;
  341.   sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
  342.  
  343.   argfile = fopen (rf, "w");
  344.   if (argfile == 0)
  345.     pfatal_with_name (rf);
  346.  
  347.   for (i=1; argv[i]; i++)
  348.     {
  349.       char *cp;
  350.       for (cp = argv[i]; *cp; cp++)
  351.     {
  352.       if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
  353.         fputc ('\\', argfile);
  354.       fputc (*cp, argfile);
  355.     }
  356.       fputc ('\n', argfile);
  357.     }
  358.   fclose (argfile);
  359.  
  360.   i = system (scmd);
  361.  
  362.   remove (rf);
  363.   
  364.   if (i == -1)
  365.     perror_exec (program);
  366. }
  367. #endif /* __MSDOS__ */
  368.  
  369. int
  370. main (argc, argv)
  371.      int argc;
  372.      char **argv;
  373. {
  374.   register int i, j = 0;
  375.   register char *p;
  376.   int verbose = 0;
  377.  
  378.   /* This will be 0 if we encounter a situation where we should not
  379.      link in libstdc++, or 2 if we should link in libg++ as well.  */
  380.   int library = 1;
  381.  
  382.   /* Used to track options that take arguments, so we don't go wrapping
  383.      those with -xc++/-xnone.  */
  384.   char *quote = NULL;
  385.  
  386.   /* The new argument list will be contained in this.  */
  387.   char **arglist;
  388.  
  389.   /* The name of the compiler we will want to run---by default, it
  390.      will be the definition of `GCC_NAME', e.g., `gcc'.  */
  391.   char *gcc = GCC_NAME;
  392.  
  393.   /* Non-zero if we saw a `-xfoo' language specification on the
  394.      command line.  Used to avoid adding our own -xc++ if the user
  395.      already gave a language for the file.  */
  396.   int saw_speclang = 0;
  397.  
  398.   /* Non-zero if we saw `-lm' or `-lmath' on the command line.  */
  399.   char *saw_math = 0;
  400.  
  401.   /* The number of arguments being added to what's in argv.  By
  402.      default it's one new argument (adding `-lstdc++').  We use this
  403.      to track the number of times we've inserted -xc++/-xnone as well.  */
  404.   int added = 1;
  405.  
  406.   /* An array used to flag each argument that needs a bit set for
  407.      LANGSPEC or MATHLIB.  */
  408.   int *args;
  409.  
  410.   p = argv[0] + strlen (argv[0]);
  411.  
  412.   /* If we're called as g++ (or i386-aout-g++), link in libg++ as well.  */
  413.  
  414.   if (strcmp (p - 3, "g++") == 0)
  415.     {
  416.       library = 2;
  417.       ++added;
  418.     }
  419.  
  420.   while (p != argv[0] && p[-1] != '/')
  421.     --p;
  422.   programname = p;
  423.  
  424.   if (argc == 1)
  425.     fatal ("No input files specified.\n");
  426.  
  427. #ifndef __MSDOS__
  428.   /* We do a little magic to find out where the main gcc executable
  429.      is.  If they ran us as /usr/local/bin/g++, then we will look
  430.      for /usr/local/bin/gcc; similarly, if they just ran us as `g++',
  431.      we'll just look for `gcc'.  */
  432.   if (p != argv[0])
  433.     {
  434.       *--p = '\0';
  435.       gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1)
  436.                  * sizeof (char));
  437.       sprintf (gcc, "%s/%s", argv[0], GCC_NAME);
  438.     }
  439. #endif
  440.  
  441.   args = (int *) malloc (argc * sizeof (int));
  442.   bzero ((char *) args, argc * sizeof (int));
  443.  
  444.   for (i = 1; i < argc; i++)
  445.     {
  446.       /* If the previous option took an argument, we swallow it here.  */
  447.       if (quote)
  448.     {
  449.       quote = NULL;
  450.       continue;
  451.     }
  452.  
  453.       if (argv[i][0] == '\0' || argv[i][1] == '\0')
  454.     continue;
  455.  
  456.       if (argv[i][0] == '-')
  457.     {
  458.       if (library != 0 && strcmp (argv[i], "-nostdlib") == 0)
  459.         {
  460.           added--;
  461.           library = 0;
  462.         }
  463.       else if (strcmp (argv[i], "-lm") == 0
  464.            || strcmp (argv[i], "-lmath") == 0)
  465.         args[i] |= MATHLIB;
  466.       else if (strcmp (argv[i], "-v") == 0)
  467.         {
  468.           verbose = 1;
  469.           if (argc == 2)
  470.         {
  471.           /* If they only gave us `-v', don't try to link
  472.              in libg++.  */ 
  473.           added--;
  474.           library = 0;
  475.         }
  476.         }
  477.       else if (strncmp (argv[i], "-x", 2) == 0)
  478.         saw_speclang = 1;
  479.       else if (((argv[i][2] == '\0'
  480.              && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
  481.             || strcmp (argv[i], "-Tdata") == 0))
  482.         quote = argv[i];
  483.       else if (library != 0 && ((argv[i][2] == '\0'
  484.              && (char *) strchr ("cSEM", argv[i][1]) != NULL)
  485.             || strcmp (argv[i], "-MM") == 0))
  486.         {
  487.           /* Don't specify libraries if we won't link, since that would
  488.          cause a warning.  */
  489.           added--;
  490.           library = 0;
  491.         }
  492.       else
  493.         /* Pass other options through.  */
  494.         continue;
  495.     }
  496.       else
  497.     {
  498.       int len; 
  499.  
  500.       if (saw_speclang)
  501.         {
  502.           saw_speclang = 0;
  503.           continue;
  504.         }
  505.  
  506.       /* If the filename ends in .c or .i, put options around it.
  507.          But not if a specified -x option is currently active.  */
  508.       len = strlen (argv[i]);
  509.       if (len > 2
  510.           && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
  511.           && argv[i][len - 2] == '.')
  512.         {
  513.           args[i] |= LANGSPEC;
  514.           added += 2;
  515.         }
  516.     }
  517.     }
  518.  
  519.   if (quote)
  520.     fatal ("argument to `%s' missing\n", quote);
  521.  
  522.   if (added)
  523.     {
  524.       arglist = (char **) malloc ((argc + added + 1) * sizeof (char *));
  525.  
  526.       for (i = 1, j = 1; i < argc; i++, j++)
  527.     {
  528.       arglist[j] = argv[i];
  529.  
  530.       /* Make sure -lg++ is before the math library, since libg++
  531.          itself uses those math routines.  */
  532.       if (!saw_math && (args[i] & MATHLIB) && library)
  533.         {
  534.           --j;
  535.           saw_math = argv[i];
  536.         }
  537.  
  538.       /* Wrap foo.c and foo.i files in a language specification to
  539.          force the gcc compiler driver to run cc1plus on them.  */
  540.       if (args[i] & LANGSPEC)
  541.         {
  542.           int len = strlen (argv[i]);
  543.           if (argv[i][len - 1] == 'i')
  544.         arglist[j++] = "-xc++-cpp-output";
  545.           else
  546.         arglist[j++] = "-xc++";
  547.           arglist[j++] = argv[i];
  548.           arglist[j] = "-xnone";
  549.         }
  550.     }
  551.  
  552.       /* Add `-lg++' if we haven't already done so.  */
  553.       if (library == 2)
  554.     arglist[j++] = "-lg++";
  555.       if (library)
  556.     arglist[j++] = "-lstdc++";
  557.       if (saw_math)
  558.     arglist[j++] = saw_math;
  559.  
  560.       arglist[j] = NULL;
  561.     }
  562.   else
  563.     /* No need to copy 'em all.  */
  564.     arglist = argv;
  565.  
  566.   arglist[0] = gcc;
  567.  
  568.   if (verbose)
  569.     {
  570.       if (j == 0)
  571.     j = argc;
  572.  
  573.       for (i = 0; i < j; i++)
  574.     fprintf (stderr, " %s", arglist[i]);
  575.       fprintf (stderr, "\n");
  576.     }
  577. #if !defined(OS2) && !defined (_WIN32)
  578. #ifdef __MSDOS__
  579.   run_dos (gcc, arglist);
  580. #else /* !__MSDOS__ */
  581.   if (execvp (gcc, arglist) < 0)
  582.     pfatal_with_name (gcc);
  583. #endif /* __MSDOS__ */
  584. #else /* OS2 or _WIN32 */
  585.   if (spawnvp (1, gcc, arglist) < 0)
  586.     pfatal_with_name (gcc);
  587. #endif
  588.  
  589.   return 0;
  590. }
  591.